package com.roads.site.service.impl;

import com.roads.common.config.MasterConfig;
import com.roads.common.constant.Constants;
import com.roads.common.constant.ResultConstants;
import com.roads.common.core.domain.AjaxResult;
import com.roads.common.core.domain.ExcelResult;
import com.roads.common.core.domain.FileEntity;
import com.roads.common.exception.file.InvalidExtensionException;
import com.roads.common.utils.DateUtils;
import com.roads.common.utils.DictUtils;
import com.roads.common.utils.RegexUtils;
import com.roads.common.utils.SecurityUtils;
import com.roads.common.utils.StringUtils;
import com.roads.common.utils.file.FileUploadUtils;
import com.roads.common.utils.file.FileUtils;
import com.roads.common.utils.file.MimeTypeUtils;
import com.roads.common.utils.uuid.IdUtils;
import com.roads.site.constant.LabourConstant;
import com.roads.site.domain.SiteLabourBattalion;
import com.roads.site.domain.SiteLabourPost;
import com.roads.site.domain.SiteLabourStaff;
import com.roads.site.domain.SiteLabourStaffRecord;
import com.roads.site.domain.SiteLabourTeam;
import com.roads.site.domain.card.CardBackModel;
import com.roads.site.domain.card.CardFrontModel;
import com.roads.site.domain.card.CardModel;
import com.roads.site.domain.vo.StaffBasicModel;
import com.roads.site.domain.vo.StaffEnterModel;
import com.roads.site.domain.vo.ZipResult;
import com.roads.site.mapper.SiteLabourBattalionMapper;
import com.roads.site.mapper.SiteLabourPostMapper;
import com.roads.site.mapper.SiteLabourStaffMapper;
import com.roads.site.mapper.SiteLabourStaffRecordMapper;
import com.roads.site.mapper.SiteLabourTeamMapper;
import com.roads.site.service.ISiteLabourStaffService;
import com.roads.site.utils.BaiduHttpUtils;
import com.roads.site.utils.CardUtils;
import com.roads.system.domain.DictProvince;
import com.roads.system.mapper.DictMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 农民工花名册Service业务层处理
 * 
 * @author nhp
 * @date 2022-10-27
 */
@Service
public class SiteLabourStaffServiceImpl implements ISiteLabourStaffService {

    @Autowired
    private SiteLabourStaffMapper mapper;

    @Autowired
    private SiteLabourStaffRecordMapper staffRecordMapper;

    @Autowired
    private SiteLabourBattalionMapper battalionMapper;

    @Autowired
    private SiteLabourTeamMapper teamMapper;

    @Autowired
    private SiteLabourPostMapper postMapper;

    @Autowired
    private DictMapper dictMapper;

    /**
     * 根据主键ID查询详情
     * 
     * @param id 农民工花名册主键
     * @return 农民工花名册
     */
    @Override
    public SiteLabourStaff getModelById(Integer id) {
        return mapper.getModelById(id);
    }

    /**
     * 查询列表
     * 
     * @param model 农民工花名册
     * @return 农民工花名册
     */
    @Override
    public List<SiteLabourStaff> selectModelList(SiteLabourStaff model) {
        return mapper.selectModelList(model);
    }

    /**
     * 根据身份证号查询劳务工
     *
     * @param idNo 身份证号
     * @return 劳务工集合
     */
    @Override
    public List<SiteLabourStaff> selectModeListByIdNo(String idNo) {
        return mapper.selectModeListByIdNo(idNo);
    }

    /**
     * 查询所有劳务工信息
     *
     * @return 所有劳务工集合
     */
    @Override
    public List<SiteLabourStaff> selectModelListAll() {
        return mapper.selectModelListAll();
    }

    /**
     * 劳务工下拉框
     *
     * @param institutionCode 标段编号
     * @return 结果
     */
    @Override
    public List<SiteLabourStaff> dropDownListBySalary(String institutionCode, Integer masterId) {
        return mapper.dropDownListBySalary(institutionCode, masterId);
    }

    /**
     * 根据id集合查询劳务工集合
     *
     * @param ids id 集合
     * @return 劳务工集合
     */
    @Override
    public List<SiteLabourStaff> selectModelListByIds(Integer[] ids) {
        return mapper.selectModelListByIds(ids);
    }

    /**
     * 根据项目ID/状态查询劳务工数量
     *
     * @param projectId 项目ID
     * @param status 状态
     * @return 数量
     */
    @Override
    public int getStaffCountByProjectId(Integer projectId, String status) {
        return mapper.getStaffCountByProjectId(projectId, status);
    }

    /**
     * 根据项目ID/用户/机构类型/状态查询劳务工数量
     *
     * @param projectId 项目ID
     * @param userName 用户
     * @param status 状态
     * @return 数量
     */
    @Override
    public int getStaffCountByProjectIdAndUser(Integer projectId, String userName, String status) {
        return mapper.getStaffCountByProjectIdAndUser(projectId, userName, status);
    }

    /**
     * 新增
     * 
     * @param model 农民工花名册
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(SiteLabourStaff model) {
        // uuid
        String uuid = IdUtils.simpleUuid();
        model.setUuid(uuid);
        model.setEnterMode(LabourConstant.STAFF_MANUAL_ENTRY);
        model.setStatus(LabourConstant.STAFF_STATUS_PENDING);
        model.setUploadCard(Constants.NO);
        mapper.insert(model);
        return 1;
    }

    /**
     * 身份证上传
     *
     * @param cardFrontFile 身份证正面
     * @param cardBackFile 身份证背面
     * @param institutionCode 标段编号
     * @param front 身份证正面对象
     * @param back 身份证背面对象
     * @return 结果
     */
    @Override
    public AjaxResult cardUpload(MultipartFile cardFrontFile, MultipartFile cardBackFile, String institutionCode, CardFrontModel front, CardBackModel back) {
        // 查看该劳务工是否在其他项目标段在岗状态
        List<SiteLabourStaff> dbList = mapper.selectModeListByIdNo(front.getIdNo());
        SiteLabourStaff real = null;
        for (SiteLabourStaff staff : dbList) {
            if (staff.getInstitutionCode().equals(institutionCode)) {
                real = staff;
            }
//            if (!staff.getInstitutionCode().equals(institutionCode) && LabourConstant.STAFF_STATUS_MOBILIZED.equals(staff.getStatus())) {
//                return AjaxResult.error("[" + staff.getIdNo() + "]在其他项目标段为在岗状态，不能进行添加。");
//            }
        }
        // 更新劳务工信息或者新增劳务工信息
        if (StringUtils.isNotNull(real)) {
            try {
                SiteLabourStaff update = initUpdateCardStaff(real, cardFrontFile, cardBackFile, front, back);
                mapper.update(update);
            } catch (InvalidExtensionException | IOException e) {
                e.printStackTrace();
                return AjaxResult.error("上传身份证照片失败，请联系管理员");
            }
        } else {
            try {
                SiteLabourStaff staff = initCardStaff(cardFrontFile, cardBackFile, institutionCode, front, back);
                mapper.insert(staff);
            } catch (InvalidExtensionException | IOException e) {
                e.printStackTrace();
                return AjaxResult.error("上传身份证照片失败，请联系管理员");
            }

        }
        return AjaxResult.success();
    }

    /**
     * 身份证zip上传
     *
     * @param institutionCode 标段编号
     * @param zipPath zip文件路径
     * @param tempPath 临时路径
     * @return 结果
     */
    @Override
    public AjaxResult cardZipUpload(String institutionCode, String zipPath, String tempPath) {
        AjaxResult ajaxResult = new AjaxResult();
        // 获取文件夹下的所有文件
        File directory = new File(zipPath);
        String[] fileNames = directory.list();
        if (StringUtils.isNull(fileNames) || fileNames.length == 0) {
            ajaxResult.put(ResultConstants.RESULT_TAG_STATUS, ResultConstants.RESULT_ERROR);
            ajaxResult.put(ResultConstants.RESULT_TAG_MSG, "压缩文件为空");
            return ajaxResult;
        }
        List<ZipResult> zipResults = new ArrayList<>();
        Map<String, File> fileMap = new HashMap<>();
        for (int i = 0; i < fileNames.length; i++) {
            ZipResult zipResult = new ZipResult();
            StringBuilder content = new StringBuilder();
            String fileNameFull = fileNames[i];
            zipResult.setName(fileNameFull);
            String fileName = fileNameFull.substring(0, fileNames[i].lastIndexOf("."));
            // 验证文件名称是否正确 身份证号+英文减号组成
            boolean validNameResult = validFileName(fileName);
            if (!validNameResult) {
                content.append("文件名称格式不正确;");
                zipResult.setStatus(ResultConstants.RESULT_ERROR);
            }
            if (!ResultConstants.RESULT_ERROR.equals(zipResult.getStatus())) {
                File file = new File(zipPath + "/" + fileNameFull);
                boolean validSize = file.length() > CardUtils.FILE_MAX_SIZE;
                // 先判断文件大小，再判断文件是否为图片
                if (validSize) {
                    content.append("文件大小不能大于2M;");
                    zipResult.setStatus(ResultConstants.RESULT_ERROR);
                }
                if (!validSize) {
                    boolean imageResult = FileUtils.isImage(file);
                    if (!imageResult) {
                        content.append("文件非图片格式;");
                        zipResult.setStatus(ResultConstants.RESULT_ERROR);
                    }
                }
                fileMap.put(fileNameFull, file);
            }
            if (!ResultConstants.RESULT_ERROR.equals(zipResult.getStatus())) {
                boolean pairResult = validFilePair(fileName, fileNames);
                if (!pairResult) {
                    content.append("未找到身份证另一面照片;");
                    zipResult.setStatus(ResultConstants.RESULT_ERROR);
                }
            }
            zipResult.setContent(content.toString());
            zipResults.add(zipResult);
        }
        // 上传身份证照片
        try {
            uploadCardZip(ajaxResult, zipResults, fileNames, fileMap, institutionCode);
            int success = 0;
            int error = 0;
            int count = 0;
            for (ZipResult zipResult : zipResults) {
                if (ResultConstants.RESULT_SUCCESS.equals(zipResult.getStatus())) {
                    success++;
                } else {
                    error++;
                }
                count++;
            }
            String msg = "";
            if (error == 0) {
                msg = "导入成功,共导入" + count + "个文件.";
                ajaxResult.put(ResultConstants.RESULT_TAG_STATUS, ResultConstants.RESULT_SUCCESS);
            } else {
                msg = "导入完成,共计" + count + "个文件,导入成功" + success + "个文件,导入失败" + error + "个文件.";
                ajaxResult.put(ResultConstants.RESULT_TAG_STATUS, ResultConstants.RESULT_ERROR);
            }
            ajaxResult.put(ResultConstants.RESULT_TAG_MSG, msg);
            ajaxResult.put(ResultConstants.RESULT_TAG_ROWS, zipResults);
        } catch (Exception e) {
            FileUtils.deleteDirectory(new File(tempPath));
            e.printStackTrace();
        }
        FileUtils.deleteDirectory(new File(tempPath));
        return ajaxResult;
    }

    /**
     * 验证身份证文件是否正确
     *
     * @param fileName 文件名称
     * @return 结果
     */
    private boolean validFileName(String fileName) {
        String[] fileSplit = fileName.split("-");
        if (fileSplit.length != 2) {
            return false;
        }
        String idNo = fileSplit[0];
        String suffix = fileSplit[1];
        if (!CardUtils.is18CardNo(idNo)) {
            return false;
        }
        if (!"1".equals(suffix) && !"2".equals(suffix)) {
            return false;
        }
        return true;
    }

    /**
     * 身份证正反面配对
     *
     * @param fileName 文件名称
     */
    private boolean validFilePair(String fileName, String[] fileNames) {
        String[] fileSplit = fileName.split("-");
        String idNo = fileSplit[0];
        String suffix = fileSplit[1];
        String otherFileName = "";
        if ("1".equals(suffix)) {
            otherFileName = idNo + "-" + "2";
        } else {
            otherFileName = idNo + "-" + "1";
        }
        for (int i = 0; i < fileNames.length; i++) {
            String fileNameFull = fileNames[i];
            String name = fileNameFull.substring(0, fileNames[i].lastIndexOf("."));
            if (otherFileName.equals(name)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 批量上传身份证
     *
     * @param ajaxResult 结果
     * @param zipResults zip
     * @param fileMap 文件map
     * @param institutionCode 标段编号
     * @return 结果
     */
    public AjaxResult uploadCardZip(AjaxResult ajaxResult, List<ZipResult> zipResults, String[] fileNames, Map<String, File> fileMap, String institutionCode)
            throws Exception {
        SiteLabourStaff search = new SiteLabourStaff();
        search.setInstitutionCode(institutionCode);
        String basePath = MasterConfig.getLabourStaffPath();
        Map<String, ZipResult> realUploadMap = new HashMap<>();
        String token = BaiduHttpUtils.getAuth();
        for (ZipResult zipResult : zipResults) {
            StringBuilder content = new StringBuilder();
            if (ResultConstants.RESULT_ERROR.equals(zipResult.getStatus())) {
                continue;
            }
            String fileNameFull = zipResult.getName();
            String fileName = fileNameFull.substring(0, fileNameFull.lastIndexOf("."));
            String[] fileSplit = fileName.split("-");
            String idNo = fileSplit[0];
            ZipResult repeat = realUploadMap.get(idNo);
            if (StringUtils.isNotNull(repeat)) {
                zipResult.setStatus(repeat.getStatus());
                zipResult.setContent(repeat.getContent());
                continue;
            }
            SiteLabourStaff updateStaff = mapper.getModelByIdNo(idNo, institutionCode);
            int type = 0;
            if (StringUtils.isNotNull(updateStaff)) {
                if (Constants.YES.equals(updateStaff.getUploadCard())) {
                    content.append("已上传身份证照片;");
                    zipResult.setStatus(ResultConstants.RESULT_ERROR);
                } else {
                    type = 2;
                }
            } else {
                type = 1;
            }
            if (!ResultConstants.RESULT_ERROR.equals(zipResult.getStatus())) {
                String frontFileName = findFileName(idNo + "-1", fileNames);
                String backFileName = findFileName(idNo + "-2", fileNames);
                File frontFile = fileMap.get(frontFileName);
                File backFile = fileMap.get(backFileName);
                CardModel card = CardUtils.cardUpload(token, frontFile, backFile);
                if (card.getStatus().equals(ResultConstants.RESULT_ERROR)) {
                    content.append(card.getContent());
                    zipResult.setStatus(ResultConstants.RESULT_ERROR);
                }
                if (!ResultConstants.RESULT_ERROR.equals(zipResult.getStatus())) {
                    // 上传文件路径
                    String filePath = basePath + "/" + idNo + "/photo";
                    String realFrontFileName = "cardFront" + frontFileName.substring(frontFileName.lastIndexOf("."));
                    String realBackFileName = "backFront" + frontFileName.substring(backFileName.lastIndexOf("."));
                    String frontPath = FileUtils.writeBytes(card.getCardFront().getBytes(), filePath, realFrontFileName, false);
                    String backPath = FileUtils.writeBytes(card.getCardBack().getBytes(), filePath, realBackFileName, false);
                    // 上传身份证头像
                    String photoBase64 = card.getCardFront().getPhoto();
                    byte[] photoBytes = FileUtils.readBase64(photoBase64);
                    String photoPath = FileUtils.writeBytes(photoBytes, filePath, "photo");
                    if (type == 1) {
                        // 新增
                        SiteLabourStaff insert = createStaff(frontPath, backPath, photoPath, institutionCode, card.getCardFront(), card.getCardBack());
                        mapper.insert(insert);
                    } else {
                        // 修改
                        SiteLabourStaff update = createUpdateStaff(updateStaff, frontPath, backPath, photoPath, card.getCardFront(), card.getCardBack());
                        mapper.update(update);
                    }
                    content.append("正确");
                    zipResult.setStatus(ResultConstants.RESULT_SUCCESS);
                }
            }
            zipResult.setContent(content.toString());
            realUploadMap.put(idNo, zipResult);
        }
        return ajaxResult;
    }

    private String findFileName(String fileName, String[] fileNames) {
        for (int i = 0; i < fileNames.length; i++) {
            String fileNameFull = fileNames[i];
            String realName = fileNameFull.substring(0, fileNameFull.lastIndexOf("."));
            if (fileName.equals(realName)) {
                return fileNameFull;
            }
        }
        return "";
    }

    /**
     * 身份证照片初始化劳务工
     *
     * @param cardFrontFile 身份证正面
     * @param cardBackFile 身份证背面
     * @param institutionCode 标段编号
     * @param front 正面信息
     * @param back 背面信息
     * @return 劳务工
     * @throws IOException IO异常
     * @throws InvalidExtensionException 构建异常
     */
    private SiteLabourStaff initCardStaff(MultipartFile cardFrontFile, MultipartFile cardBackFile, String institutionCode, CardFrontModel front, CardBackModel back) throws IOException, InvalidExtensionException {
        // 相关文件上传
        String basePath = MasterConfig.getLabourStaffPath() + "/" + front.getIdNo() + "/photo";
        // 上传身份证正反面
        FileEntity frontFile = FileUploadUtils.cardUpload(basePath, cardFrontFile, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, "cardFront");
        FileEntity backFile = FileUploadUtils.cardUpload(basePath, cardBackFile, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, "cardBack");
        // 上传身份证头像
        String photoBase64 = front.getPhoto();
        byte[] photoBytes = FileUtils.readBase64(photoBase64);
        String photoPath = FileUtils.writeBytes(photoBytes, basePath, "photo");
        return createStaff(frontFile.getFilePath(), backFile.getFilePath(), photoPath, institutionCode, front, back);
    }

    /**
     * 创建劳务工实体
     *
     * @param frontPath 正面照路径
     * @param backPath 背面照路径
     * @param photoPath 头像路径
     * @param institutionCode 标段编号
     * @param front 正面照片
     * @param back 背面照片
     * @return 劳务工
     */
    private SiteLabourStaff createStaff(String frontPath, String backPath, String photoPath, String institutionCode, CardFrontModel front, CardBackModel back) {
        SiteLabourStaff staff = new SiteLabourStaff();
        // uuid
        String uuid = IdUtils.simpleUuid();
        staff.setUuid(uuid);
        staff.setInstitutionCode(institutionCode);
        staff.setIdNo(front.getIdNo());
        staff.setName(front.getName());
        staff.setSex(front.getSex());
        staff.setNation(front.getNation());
        staff.setBirthDate(DateUtils.dateTime(DateUtils.YYYYMMDD, front.getBirthday()));
        staff.setAge(CardUtils.countAge(front.getIdNo()));
        staff.setAddress(front.getAddress());
        staff.setSigningOrg(back.getSigningOrg());
        staff.setUploadCard(Constants.YES);
        staff.setEnterMode(LabourConstant.STAFF_CARD_ENTRY);
        staff.setPhoto(photoPath);
        staff.setCardFrontPhoto(frontPath);
        staff.setCardBackPhoto(backPath);
        staff.setStatus(LabourConstant.STAFF_STATUS_PENDING);
        staff.setCreateBy(SecurityUtils.getUsername());
        staff.setCreateTime(DateUtils.getNowDate());
        return staff;
    }

    /**
     * 身份证照片初始化劳务工--更新
     *
     * @param update 需要更新的劳务工
     * @param cardFrontFile 身份证正面
     * @param cardBackFile 身份证背面
     * @param front 正面信息
     * @param back 背面信息
     * @return 劳务工
     * @throws IOException IO异常
     * @throws InvalidExtensionException 构建异常
     */
    private SiteLabourStaff initUpdateCardStaff(SiteLabourStaff update, MultipartFile cardFrontFile, MultipartFile cardBackFile, CardFrontModel front, CardBackModel back) throws IOException, InvalidExtensionException {
        // 相关文件上传
        String basePath = MasterConfig.getLabourStaffPath() + "/" + front.getIdNo() + "/photo";
        // 上传身份证正反面
        FileEntity frontFile = FileUploadUtils.cardUpload(basePath, cardFrontFile, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, "cardFront");
        FileEntity backFile = FileUploadUtils.cardUpload(basePath, cardBackFile, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, "cardBack");
        // 上传身份证头像
        String photoBase64 = front.getPhoto();
        byte[] photoBytes = FileUtils.readBase64(photoBase64);
        String photoPath = FileUtils.writeBytes(photoBytes, basePath, "photo");
        return createUpdateStaff(update, frontFile.getFilePath(), backFile.getFilePath(), photoPath, front, back);
    }

    private SiteLabourStaff createUpdateStaff(SiteLabourStaff update, String frontPath, String backPath, String photoPath, CardFrontModel front, CardBackModel back) {
        update.setIdNo(front.getIdNo());
        update.setName(front.getName());
        update.setSex(front.getSex());
        update.setNation(front.getNation());
        update.setBirthDate(DateUtils.dateTime(DateUtils.YYYYMMDD, front.getBirthday()));
        update.setAge(CardUtils.countAge(front.getIdNo()));
        if (StringUtils.isEmpty(update.getAddress())) {
            update.setAddress(front.getAddress());
        }
        update.setSigningOrg(back.getSigningOrg());
        update.setUploadCard(Constants.YES);
        update.setPhoto(photoPath);
        update.setCardFrontPhoto(frontPath);
        update.setCardBackPhoto(backPath);
        update.setUpdateBy(SecurityUtils.getUsername());
        update.setUpdateTime(DateUtils.getNowDate());
        return update;
    }

    /**
     * excel批量导入劳务工
     *
     * @param list excel劳务工集合
     * @param institutionCode 标段编号
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult importBasicData(List<StaffBasicModel> list, String institutionCode) {
        AjaxResult ajaxResult = new AjaxResult();
        String loginUser = SecurityUtils.getUsername();
        Date nowDate = DateUtils.getNowDate();
        // 数据库存在的劳务工信息
        List<SiteLabourStaff> dbList = mapper.selectModelListAll();
        List<StaffBasicModel> tempList = new ArrayList<>();
        List<DictProvince> provinceList = dictMapper.getProvinceList();
        List<SiteLabourStaff> insertList = new ArrayList<>();
        List<SiteLabourStaff> updateList = new ArrayList<>();
        // excel导入结果集合
        List<ExcelResult> excelResults = new ArrayList<>();
        // excel起始行
        int index = 2;
        for (StaffBasicModel staff : list) {
            staff.setInstitutionCode(institutionCode);
            ExcelResult excelResult = new ExcelResult();
            StringBuilder content = new StringBuilder();
            excelResult.setRow(index);
            String validateFormat = validateFormat(staff, provinceList);
            if (StringUtils.isNotEmpty(validateFormat)) {
                content.append(validateFormat);
                excelResult.setStatus(ResultConstants.RESULT_ERROR);
            }
            // 验证excel表格数据是否有重复
            if (!ResultConstants.RESULT_ERROR.equals(excelResult.getStatus())) {
                String validateRepeat = validateRepeat(staff, tempList);
                if (StringUtils.isNotEmpty(validateRepeat)) {
                    content.append(validateRepeat);
                    excelResult.setStatus(ResultConstants.RESULT_ERROR);
                }
            }
            // 验证数据是新增还是修改
            if (!ResultConstants.RESULT_ERROR.equals(excelResult.getStatus())) {
                SiteLabourStaff update = validateInsertOrUpdate(staff, dbList);
                if (StringUtils.isNotNull(update)) {
                    updateList.add(initImportBasicUpdate(staff, update, loginUser, nowDate));
                    content.append("覆盖更新");
                } else {
                    insertList.add(initImportBasicInsert(staff, loginUser, nowDate));
                    content.append("正确");
                }
                excelResult.setStatus(ResultConstants.RESULT_SUCCESS);
            }
            excelResult.setContent(content.toString());
            staff.setRow(index);
            tempList.add(staff);
            index++;
            excelResults.add(excelResult);
        }
        boolean result = true;
        for (ExcelResult excelResult : excelResults) {
            if (ResultConstants.RESULT_ERROR.equals(excelResult.getStatus())) {
                result = false;
                break;
            }
        }
        if (result) {
            // 批量插入和更新
            if (insertList.size() > 0) {
                mapper.insertBatchBasicImport(insertList);
            }
            if (updateList.size() > 0) {
                mapper.updateBatchBasicImport(updateList);
            }
            ajaxResult.put(ResultConstants.RESULT_TAG_MSG, ResultConstants.RESULT_SUCCESS_MESSAGE);
            ajaxResult.put(ResultConstants.RESULT_TAG_STATUS, ResultConstants.RESULT_SUCCESS);
        } else {
            ajaxResult.put(ResultConstants.RESULT_TAG_MSG, ResultConstants.RESULT_ERROR_MESSAGE);
            ajaxResult.put(ResultConstants.RESULT_TAG_STATUS, ResultConstants.RESULT_ERROR);
        }
        ajaxResult.put(ResultConstants.RESULT_TAG_ROWS, excelResults);
        return ajaxResult;
    }

    /**
     * 验证数据格式
     *
     * @param staff 劳务工
     * @param provinceList 身份下拉
     * @return 结果
     */
    public String validateFormat(StaffBasicModel staff, List<DictProvince> provinceList) {
        StringBuilder sb = new StringBuilder();
        if (StringUtils.isEmpty(staff.getIdNo())) {
            sb.append("身份证号为空;");
        } else if (!CardUtils.is18CardNo(staff.getIdNo())){
            sb.append("身份证号码验证未通过;");
        }
        if (StringUtils.isEmpty(staff.getName())) {
            sb.append("姓名为空;");
        }
        if (StringUtils.isEmpty(staff.getPhone())) {
            sb.append("联系电话为空;");
        } else if (!RegexUtils.isPhone(staff.getPhone())) {
            sb.append("联系电话验证未通过;");
        }
        if (StringUtils.isNotEmpty(staff.getPoliticalStatus())) {
            String value = DictUtils.getDictLabel("sys_political_status", staff.getPoliticalStatus());
            if (StringUtils.isEmpty(value)) {
                sb.append("政治面貌格式不正确;");
            }
        }
        if (StringUtils.isNotEmpty(staff.getDegreeName())) {
            String value = DictUtils.getDictLabel("sys_degree_name", staff.getDegreeName());
            if (StringUtils.isEmpty(value)) {
                sb.append("文化程度格式不正确;");
            }
        }
        if (StringUtils.isNotEmpty(staff.getNativePlace())) {
            String value = "";
            for (DictProvince province : provinceList) {
                if (province.getName().contains(staff.getNativePlace())) {
                    value = province.getName();
                    break;
                }
            }
            if (StringUtils.isNotEmpty(value)) {
                staff.setNativePlace(value);
            } else {
                sb.append("籍贯格式不正确;");
            }
        }
        if (StringUtils.isNotEmpty(staff.getBloodType())) {
            String value = DictUtils.getDictLabel("sys_blood_type", staff.getBloodType());
            if (StringUtils.isEmpty(value)) {
                sb.append("血型格式不正确;");
            }
        }
        if (StringUtils.isNotEmpty(staff.getUrgentTel())) {
            if (!RegexUtils.isPhone(staff.getUrgentTel())) {
                sb.append("联系人联系电话验证未通过;");
            }
        }
        return sb.toString();
    }

    /**
     * 验证excel是否有重复的身份证号码和联系电话
     *
     * @param staff 导入劳务工
     * @param tempList 临时劳务工
     * @return 结果
     */
    private String validateRepeat(StaffBasicModel staff, List<StaffBasicModel> tempList) {
        for (StaffBasicModel temp : tempList) {
            if (staff.getIdNo().equals(temp.getIdNo())) {
                return "与第" + temp.getRow() + "行，身份证重复;";
            }
            if (staff.getPhone().equals(temp.getPhone())) {
                return "与第" + temp.getRow() + "行，联系电话重复;";
            }
        }
        return "";
    }

    /**
     * 验证数据时新增还是修改
     * 1.新增
     * 2.修改
     *
     * @param staff 导入劳务工
     * @param bdList 数据库劳务工集合
     * @return 结果
     */
    private SiteLabourStaff validateInsertOrUpdate(StaffBasicModel staff, List<SiteLabourStaff> bdList) {
        for (SiteLabourStaff db : bdList) {
            if (staff.getIdNo().equals(db.getIdNo()) && staff.getInstitutionCode().equals(db.getInstitutionCode())) {
                return db;
            }
        }
        return null;
    }

    private SiteLabourStaff initImportBasicInsert(StaffBasicModel staff, String userName, Date nowDate) {
        String uuid = IdUtils.simpleUuid();
        SiteLabourStaff insert = new SiteLabourStaff();
        insert.setUuid(uuid);
        insert.setInstitutionCode(staff.getInstitutionCode());
        insert.setIdNo(staff.getIdNo());
        insert.setName(staff.getName());
        insert.setSex(CardUtils.judgeGender(staff.getIdNo()));
        insert.setAge(CardUtils.countAge(staff.getIdNo()));
        insert.setBirthDate(CardUtils.extractBirth(staff.getIdNo()));
        insert.setAddress(staff.getAddress());
        insert.setSigningOrg(staff.getSigningOrg());
        insert.setUploadCard(Constants.NO);
        insert.setNation(staff.getNation());
        insert.setEnterMode(LabourConstant.STAFF_MANUAL_ENTRY);
        insert.setPhone(staff.getPhone());
        insert.setPoliticalStatus(staff.getPoliticalStatus());
        insert.setDegreeName(staff.getDegreeName());
        insert.setNativePlace(staff.getNativePlace());
        insert.setBloodType(staff.getBloodType());
        insert.setUrgentContact(staff.getUrgentContact());
        insert.setUrgentTel(staff.getUrgentTel());
        insert.setStatus(LabourConstant.STAFF_STATUS_PENDING);
        insert.setCreateBy(userName);
        insert.setCreateTime(nowDate);
        return insert;
    }

    private SiteLabourStaff initImportBasicUpdate(StaffBasicModel staff, SiteLabourStaff update, String userName, Date nowDate) {
        update.setIdNo(staff.getIdNo());
        update.setName(staff.getName());
        update.setSex(CardUtils.judgeGender(staff.getIdNo()));
        update.setAge(CardUtils.countAge(staff.getIdNo()));
        update.setBirthDate(CardUtils.extractBirth(staff.getIdNo()));
        update.setAddress(staff.getAddress());
        update.setSigningOrg(staff.getSigningOrg());
        update.setNation(staff.getNation());
        update.setPhone(staff.getPhone());
        update.setPoliticalStatus(staff.getPoliticalStatus());
        update.setDegreeName(staff.getDegreeName());
        update.setNativePlace(staff.getNativePlace());
        update.setBloodType(staff.getBloodType());
        update.setUrgentContact(staff.getUrgentContact());
        update.setUrgentTel(staff.getUrgentTel());
        update.setUpdateBy(userName);
        update.setUpdateTime(nowDate);
        return update;
    }


    /**
     * 修改
     * 
     * @param model 农民工花名册
     * @return 结果
     */
    @Override
    public int update(SiteLabourStaff model) {
        return mapper.update(model);
    }

    /**
     * 批量删除
     * 
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    public int deleteByIds(Integer[] ids) {
        return mapper.deleteByIds(ids);
    }

    /**
     * 删除
     * 
     * @param id 农民工花名册主键
     * @return 结果
     */
    @Override
    public int delete(Integer id) {
        return mapper.delete(id);
    }

    /**
     * 劳务工进场
     *
     * @param staffRecord 劳务工进场记录
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int enter(SiteLabourStaffRecord staffRecord) {
        SiteLabourStaff staff = mapper.getModelById(staffRecord.getStaffId());
        SiteLabourBattalion battalion = battalionMapper.getModelById(staffRecord.getBattalionId());
        SiteLabourTeam team = teamMapper.getModelById(staffRecord.getTeamId());
        SiteLabourPost post = postMapper.getModelById(staffRecord.getPostId());
        staff.setEnterDate(staffRecord.getEnterDate());
        staff.setExitDate(null);
        staff.setStatus(LabourConstant.STAFF_STATUS_MOBILIZED);
        staff.setBattalionId(battalion.getBattalionId());
        staff.setBattalionName(battalion.getBattalionName());
        staff.setTeamId(team.getTeamId());
        staff.setTeamName(team.getTeamName());
        staff.setPostId(post.getPostId());
        staff.setPostName(post.getPostName());
        staff.setIsMonitor(staffRecord.getIsMonitor());
        staffRecord.setInstitutionCode(staff.getInstitutionCode());
        staffRecord.setCreateBy(SecurityUtils.getUsername());
        staffRecord.setCreateTime(DateUtils.getNowDate());
        mapper.update(staff);
        staffRecordMapper.insert(staffRecord);
        return 1;
    }

    /**
     * 劳务工退场
     *
     * @param staff 劳务工信息
     * @param staffRecord 劳务工进场记录
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int exit(SiteLabourStaff staff, SiteLabourStaffRecord staffRecord) {
        staff.setExitDate(staffRecord.getExitDate());
        staff.setStatus(LabourConstant.STAFF_STATUS_DEPARTURE);
        mapper.update(staff);
        SiteLabourStaffRecord lastEnter = staffRecordMapper.getLastEnter(staff.getIdNo());
        lastEnter.setExitDate(staffRecord.getExitDate());
        lastEnter.setStatus(LabourConstant.STAFF_STATUS_DEPARTURE);
        lastEnter.setUpdateBy(SecurityUtils.getUsername());
        lastEnter.setUpdateTime(DateUtils.getNowDate());
        staffRecordMapper.update(lastEnter);
        return 1;
    }

    /**
     * 劳务工批量退场
     *
     * @param ids id数组
     * @param exitDate 退场日期
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchExit(Integer[] ids, Date exitDate) {
        for (int i = 0; i < ids.length; i++) {
            SiteLabourStaff staff = mapper.getModelById(ids[i]);
            staff.setExitDate(exitDate);
            staff.setStatus(LabourConstant.STAFF_STATUS_DEPARTURE);
            mapper.update(staff);
            SiteLabourStaffRecord lastEnter = staffRecordMapper.getLastEnter(staff.getIdNo());
            lastEnter.setExitDate(exitDate);
            lastEnter.setStatus(LabourConstant.STAFF_STATUS_DEPARTURE);
            lastEnter.setUpdateBy(SecurityUtils.getUsername());
            lastEnter.setUpdateTime(DateUtils.getNowDate());
            staffRecordMapper.update(lastEnter);
        }
        return 1;
    }

    /**
     * excel批量导入劳务工进场信息
     *
     * @param list excel劳务工进场集合
     * @param institutionCode 标段编号
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult importEnterData(List<StaffEnterModel> list, String institutionCode) {
        AjaxResult ajaxResult = new AjaxResult();
        // excel导入结果集合
        List<ExcelResult> excelResults = new ArrayList<>();
        // 临时存放，验证excel表格数据是否有重复用
        List<StaffEnterModel> tempList = new ArrayList<>();
        // excel起始行
        int index = 2;
        for (StaffEnterModel enter : list) {
            ExcelResult excelResult = new ExcelResult();
            StringBuilder content = new StringBuilder();
            excelResult.setRow(index);
            // 验证数据格式是否正确
            String validateFormat = validateFormat(enter);
            if (StringUtils.isNotEmpty(validateFormat)) {
                content.append(validateFormat);
                excelResult.setStatus(ResultConstants.RESULT_ERROR);
            }
            // 验证数据是否重复
            if (!ResultConstants.RESULT_ERROR.equals(excelResult.getStatus())) {
                String validateRepeat = validateRepeat(enter, tempList);
                if (StringUtils.isNotEmpty(validateRepeat)) {
                    content.append(validateRepeat);
                    excelResult.setStatus(ResultConstants.RESULT_ERROR);
                }
            }
            // 验证劳务工是否可以进场
            if (!ResultConstants.RESULT_ERROR.equals(excelResult.getStatus())) {
                String validateResult = validateStaffIsExitsAndEnter(enter, institutionCode);
                if (StringUtils.isNotEmpty(validateResult)) {
                    content.append(validateResult);
                    excelResult.setStatus(ResultConstants.RESULT_ERROR);
                }
            }
            // 正确数据处理
            if (!ResultConstants.RESULT_ERROR.equals(excelResult.getStatus())) {
                content.append("正确");
                excelResult.setStatus(ResultConstants.RESULT_SUCCESS);
            }
            excelResult.setContent(content.toString());
            enter.setRow(index);
            tempList.add(enter);
            index++;
            excelResults.add(excelResult);
        }
        boolean result = true;
        for (ExcelResult excelResult : excelResults) {
            if (ResultConstants.RESULT_ERROR.equals(excelResult.getStatus())) {
                result = false;
                break;
            }
        }
        if (result) {
            // 处理进场信息
            batchEnter(list, institutionCode);
            ajaxResult.put(ResultConstants.RESULT_TAG_MSG, ResultConstants.RESULT_SUCCESS_MESSAGE);
            ajaxResult.put(ResultConstants.RESULT_TAG_STATUS, ResultConstants.RESULT_SUCCESS);
        } else {
            ajaxResult.put(ResultConstants.RESULT_TAG_MSG, ResultConstants.RESULT_ERROR_MESSAGE);
            ajaxResult.put(ResultConstants.RESULT_TAG_STATUS, ResultConstants.RESULT_ERROR);
        }
        ajaxResult.put(ResultConstants.RESULT_TAG_ROWS, excelResults);
        return ajaxResult;
    }

    /**
     * 验证进场信息数据格式
     *
     * @param enter 进场信息
     * @return 结果
     */
    public String validateFormat(StaffEnterModel enter) {
        StringBuilder sb = new StringBuilder();
        if (StringUtils.isEmpty(enter.getIdNo())) {
            sb.append("身份证号为空;");
        } else if (!CardUtils.is18CardNo(enter.getIdNo())){
            sb.append("身份证号码验证未通过;");
        }
        if (StringUtils.isEmpty(enter.getName())) {
            sb.append("姓名为空;");
        }
        if (StringUtils.isNull(enter.getEnterDate())) {
            sb.append("进场日期为空;");
        }
        if (StringUtils.isEmpty(enter.getBattalionName())) {
            sb.append("施工队伍为空;");
        }
        if (StringUtils.isEmpty(enter.getTeamName())) {
            sb.append("施工班组为空;");
        }
        if (StringUtils.isEmpty(enter.getPostName())) {
            sb.append("岗位工种为空;");
        }
        if (StringUtils.isEmpty(enter.getIsMonitor())) {
            sb.append("班组长为空;");
        }
        return sb.toString();
    }

    /**
     * 验证excel是否有重复的身份证号码和姓名
     *
     * @param enter 导入劳务工进场
     * @param tempList 临时劳务工进场
     * @return 结果
     */
    private String validateRepeat(StaffEnterModel enter, List<StaffEnterModel> tempList) {
        for (StaffEnterModel temp : tempList) {
            if (enter.getIdNo().equals(temp.getIdNo())) {
                return "与第" + temp.getRow() + "行，身份证重复;";
            }
            if (enter.getName().equals(temp.getName())) {
                return "与第" + temp.getRow() + "行，姓名重复;";
            }
        }
        return "";
    }


    /**
     * 判断劳务工在其他项目标段是否已经进场,劳务工在本项目标段是否登记
     *
     * @param enter 劳务工进场信息
     * @param institutionCode 标段编号
     * @return 结果
     */
    private String validateStaffIsExitsAndEnter(StaffEnterModel enter, String institutionCode) {
        int flag = 0;
        List<SiteLabourStaff> staffList = mapper.selectModeListByIdNo(enter.getIdNo());
        if (StringUtils.isNull(staffList) || staffList.size() == 0) {
            return "劳务工未登记;";
        }
        for (SiteLabourStaff staff : staffList) {
            if (!staff.getInstitutionCode().equals(institutionCode) && LabourConstant.STAFF_STATUS_MOBILIZED.equals(staff.getStatus())) {
                return "在其他项目标段已进场;";
            }
            if (staff.getInstitutionCode().equals(institutionCode)) {
                if (!staff.getName().equals(enter.getName())) {
                    return "劳务工身份证号码和姓名不匹配;";
                }
                if (LabourConstant.STAFF_STATUS_MOBILIZED.equals(staff.getStatus())) {
                    return "劳务工已进场;";
                }
                enter.setStaffId(staff.getId());
                flag = 1;
            }
        }
        if (flag == 0) {
            return "劳务工未登记;";
        } else {
            return "";
        }
    }

    /**
     * 批量进场处理
     *
     * @param list 劳务工进场集合
     */
    private void batchEnter(List<StaffEnterModel> list, String institutionCode) {
        String loginUser = SecurityUtils.getUsername();
        Date nowDate = DateUtils.getNowDate();
        // 查询施工队伍，施工班组，岗位工种 并且转map
        List<SiteLabourBattalion> battalions = battalionMapper.selectModelListByBid(institutionCode);
        Map<String, SiteLabourBattalion> battalionMap = new HashMap<>(battalions.size());
        for (SiteLabourBattalion battalion : battalions) {
            battalionMap.put(battalion.getBattalionName(), battalion);
        }
        List<SiteLabourTeam> teams = teamMapper.selectModelListByBid(institutionCode);
        Map<String, SiteLabourTeam> teamMap = new HashMap<>(teams.size());
        for (SiteLabourTeam team : teams) {
            teamMap.put(team.getTeamName(), team);
        }
        List<SiteLabourPost> posts = postMapper.selectModelListByBid(institutionCode);
        Map<String, SiteLabourPost> postMap = new HashMap<>(posts.size());
        for (SiteLabourPost post : posts) {
            postMap.put(post.getPostName(), post);
        }
        for (StaffEnterModel enter : list) {
            // 处理劳务工花名册信息
            SiteLabourStaff staff = mapper.getModelById(enter.getStaffId());
            staff.setEnterDate(enter.getEnterDate());
            staff.setExitDate(null);
            staff.setStatus(LabourConstant.STAFF_STATUS_MOBILIZED);
            SiteLabourBattalion battalion = pairBattalion(institutionCode, enter.getBattalionName(), battalionMap, loginUser, nowDate);
            staff.setBattalionId(battalion.getBattalionId());
            staff.setBattalionName(battalion.getBattalionName());
            SiteLabourTeam team = pairTeam(institutionCode, enter.getTeamName(), teamMap, loginUser, nowDate);
            staff.setTeamId(team.getTeamId());
            staff.setTeamName(team.getTeamName());
            SiteLabourPost post = pairPost(institutionCode, enter.getPostName(), postMap, loginUser, nowDate);
            staff.setPostId(post.getPostId());
            staff.setPostName(post.getPostName());
            staff.setIsMonitor(enter.getIsMonitor());
            mapper.update(staff);
            // 处理劳务工进退场信息
            SiteLabourStaffRecord staffRecord = new SiteLabourStaffRecord();
            staffRecord.setStaffId(enter.getStaffId());
            staffRecord.setIdNo(enter.getIdNo());
            staffRecord.setInstitutionCode(institutionCode);
            staffRecord.setEnterDate(enter.getEnterDate());
            staffRecord.setBattalionId(battalion.getBattalionId());
            staffRecord.setTeamId(team.getTeamId());
            staffRecord.setPostId(post.getPostId());
            staffRecord.setIsMonitor(enter.getIsMonitor());
            staffRecord.setCreateBy(loginUser);
            staffRecord.setCreateTime(nowDate);
            staffRecordMapper.insert(staffRecord);
        }
    }

    /**
     * 匹配施工队伍
     *
     * @param institutionCode 标段编号
     * @param battalionName 施工队伍名称
     * @param battalionMap 施工队伍map集合
     * @param loginUser 当前登录用户
     * @param nowDate 当前系统时间
     * @return 施工队伍
     */
    private SiteLabourBattalion pairBattalion(String institutionCode, String battalionName, Map<String, SiteLabourBattalion> battalionMap, String loginUser, Date nowDate) {
        SiteLabourBattalion battalion = battalionMap.get(battalionName);
        if (StringUtils.isNull(battalion)) {
            battalion = new SiteLabourBattalion();
            battalion.setInstitutionCode(institutionCode);
            battalion.setBattalionName(battalionName);
            // 设置序号（排序）
            int maxSerialNumber = battalionMapper.getMaxSerialNumber(institutionCode);
            maxSerialNumber++;
            battalion.setOrderNum(maxSerialNumber);
            battalion.setCreateBy(loginUser);
            battalion.setCreateTime(nowDate);
            battalionMapper.insert(battalion);
            battalionMap.put(battalionName, battalion);
        }
        return battalion;
    }

    /**
     * 匹配施工班组
     *
     * @param institutionCode 标段编号
     * @param teamName 施工班组名称
     * @param teamMap 施工班组map集合
     * @param loginUser 当前登录用户
     * @param nowDate 当前系统时间
     * @return 施工班组
     */
    private SiteLabourTeam pairTeam(String institutionCode, String teamName, Map<String, SiteLabourTeam> teamMap, String loginUser, Date nowDate) {
        SiteLabourTeam team = teamMap.get(teamName);
        if (StringUtils.isNull(team)) {
            team = new SiteLabourTeam();
            team.setInstitutionCode(institutionCode);
            team.setTeamName(teamName);
            // 设置序号（排序）
            int maxSerialNumber = teamMapper.getMaxSerialNumber(institutionCode);
            maxSerialNumber++;
            team.setOrderNum(maxSerialNumber);
            team.setCreateBy(loginUser);
            team.setCreateTime(nowDate);
            teamMapper.insert(team);
            teamMap.put(teamName, team);
        }
        return team;
    }

    /**
     * 匹配岗位工种
     *
     * @param institutionCode 标段编号
     * @param postName 岗位工种名称
     * @param postMap 岗位工种map集合
     * @param loginUser 当前登录用户
     * @param nowDate 当前系统时间
     * @return 岗位工种
     */
    private SiteLabourPost pairPost(String institutionCode, String postName, Map<String, SiteLabourPost> postMap, String loginUser, Date nowDate) {
        SiteLabourPost post = postMap.get(postName);
        if (StringUtils.isNull(post)) {
            post = new SiteLabourPost();
            post.setInstitutionCode(institutionCode);
            post.setPostName(postName);
            // 设置序号（排序）
            int maxSerialNumber = postMapper.getMaxSerialNumber(institutionCode);
            maxSerialNumber++;
            post.setOrderNum(maxSerialNumber);
            post.setCreateBy(loginUser);
            post.setCreateTime(nowDate);
            postMapper.insert(post);
            postMap.put(postName, post);
        }
        return post;
    }

}
